package com.lz.autotest.common.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.lz.autotest.common.constant.HttpStatus;
import com.lz.autotest.common.entity.ResponseVo;
import com.lz.autotest.project.testmanage.autoTest.entity.ResultView;
import com.lz.autotest.project.testmanage.infmanage.domain.InfItemResult;
import com.lz.autotest.project.testmanage.infmanage.domain.SstInf;
import com.lz.autotest.project.testmanage.reportmanage.domain.TimeOutContant;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;

@Slf4j
public class OkHttpUtil {
    private static OkHttpClient client = new OkHttpClient().newBuilder()
            .callTimeout(600, TimeUnit.SECONDS)
            .connectTimeout(600, TimeUnit.SECONDS)
            .readTimeout(600, TimeUnit.SECONDS)
            .build();

    public static byte[] getBytes(String url) {
        Response execute = null;
        Request request = new Request.Builder()
                .method("GET", null)
                .url(url)
                .build();
        try {
            execute = client.newCall(request).execute();
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful()) {
                return execute.body().bytes();
            }
        } catch (IOException e) {
            log.error("http get 请求失败--{}", e);
        }
        return null;
    }

    /**
     * POST请求
     */
    public static ResponseVo requestPostVo(SstInf sstInf) {
        ResponseVo responseVo = ResponseVo.success();
        Response execute;
        long start = 0;
        long end = 0;
        try {
            //Header
            String method = SysUtils.isNotVoid(sstInf.getInfMethod()) ? sstInf.getInfMethod() : "POST";
            //拼装requestBody
            RequestBody requestBody = RequestBody.create(sstInf.getInfRequest(),
                    MediaType.get(SysUtils.isNotVoid(sstInf.getContentType()) ? sstInf.getContentType() : "application/json"));

            //拼装 request
            Request.Builder build = new Request.Builder()
                    .method(method, requestBody)
                    .url(sstInf.getInfFullUrl());

            if (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv()))) {
                Map<String, Object> map = DataMap.get(sstInf.getInfRealEnv());
                for (Map.Entry entry : map.entrySet()) {
                    build.addHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
            if (SysUtils.isNotVoid(sstInf.getAuthName()) && SysUtils.isNotVoid(sstInf.getAuthValue())) {
                build.addHeader(sstInf.getAuthName(), sstInf.getAuthValue());
            }
            //
            Request request = build.build();
            start = System.currentTimeMillis();
            sstInf.setRequestTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(SysUtils.isVoid(sstInf.getTimeOut()) ? TimeOutContant.TIME_OUT : Long.valueOf(sstInf.getTimeOut()), TimeUnit.MILLISECONDS);
            execute = call.execute();
            sstInf.setResponseTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            responseVo.setCode(execute.code());
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                try {
                    responseVo.setMsg(execute.body().string());
                } catch (Exception e) {
                    responseVo.setMsg(null);
                    log.error("设置返回信息失败：{}", e.getMessage());
                }
            }
        } catch (InterruptedIOException e) {
            //处理超时
            log.error("okhttp POST请求超时--{}", e.getMessage());
            responseVo.setCode(HttpStatus.TIME_OUT);
            responseVo.setMsg("请求超过预定时间");
        } catch (IOException e) {
            log.error("okhttp POST请求失败--{}", e.getMessage());
            responseVo.setCode(HttpStatus.ERROR);
            responseVo.setMsg("请求异常");
        } finally {
            end = System.currentTimeMillis();
            sstInf.setConsumeTime(end - start);
        }
        return responseVo;
    }


    public static ResponseVo requestGetVo(SstInf sstInf) {
        ResponseVo responseVo = ResponseVo.success();
        Response execute;
        long start = System.currentTimeMillis();
        long end;
        try {
            //Header
            String infRequest = SysUtils.isNotVoid(sstInf.getInfRequest()) ? sstInf.getInfRequest() : null;
            String method = SysUtils.isNotVoid(sstInf.getInfMethod()) ? sstInf.getInfMethod() : "GET";
            //拼装GET参数和URL
            String url = sstInf.getInfFullUrl();
            StringBuffer sb = new StringBuffer();
            sb.append(url);
            sb.append("?");
            if (SysUtils.isNotVoid(infRequest)) {
                try {
                    if(infRequest.length()>4){
                        HashMap map = JSONUtil.toBean(infRequest, HashMap.class);
                        StringJoiner param = new StringJoiner("&");
                        map.forEach((key, value) -> param.add(key + "=" + value));
                        sb.append(param);
                    }
                } catch (Exception e) {
                    log.error("組裝参数失败：{}", e.getMessage());
                }
            }
            Request.Builder build = new Request.Builder()
                    .url(sb.toString())
                    .method(method, null)
                    .addHeader("Content-Type", SysUtils.isNotVoid(sstInf.getContentType()) ? sstInf.getContentType() : "application/json");
            if (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv()))) {
                Map<String, Object> map = DataMap.get(sstInf.getInfRealEnv());
                for (Map.Entry entry : map.entrySet()) {
                    build.addHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
            if (SysUtils.isNotVoid(sstInf.getAuthName()) && SysUtils.isNotVoid(sstInf.getAuthValue())) {
                build.addHeader(sstInf.getAuthName(), sstInf.getAuthValue());
            }
            //
            Request request = build.build();
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(sstInf.getTimeOut() == null ? TimeOutContant.TIME_OUT : Long.valueOf(sstInf.getTimeOut()), TimeUnit.MILLISECONDS);
            execute = call.execute();
            //返回结果
            responseVo.setCode(execute.code());
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful()) {
                try {
                    responseVo.setMsg(execute.body().string());
                } catch (Exception e) {
                    responseVo.setMsg(null);
                    log.error("设置返回信息失败：{}", e.getMessage());
                }
            }
            return responseVo;
        } catch (InterruptedIOException e) {
            log.error("okhttp POST请求超时--{}", e.getMessage());
            responseVo.setCode(HttpStatus.TIME_OUT);
            responseVo.setMsg("请求超过预定超时时间:" + e.getMessage());
        } catch (IOException e) {
            responseVo.setCode(HttpStatus.ERROR);
            responseVo.setMsg("请求异常:" + e.getMessage());
        } finally {
            end = System.currentTimeMillis();
            sstInf.setConsumeTime(end - start);
        }
        sstInf.setConsumeTime(end - start);
        return responseVo;
    }


    /**
     * 自动化测试POST请求
     */
    public static ResultView requestPostByAT(SstInf sstInf) {
        Response execute = null;
        ResultView resultView = new ResultView();
        long start = System.currentTimeMillis();
        long end;
        try {
            //Header
            String method = SysUtils.isNotVoid(sstInf.getInfMethod()) ? sstInf.getInfMethod() : "POST";
            //拼装requestBody
            RequestBody requestBody = RequestBody.create(sstInf.getInfRequest(),
                    MediaType.get(SysUtils.isNotVoid(sstInf.getContentType()) ? sstInf.getContentType() : "application/json"));

            //拼装 request
            Request.Builder build = new Request.Builder()
                    .method(method, requestBody)
                    .url(sstInf.getInfFullUrl());

            if (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv()))) {
                Map<String, Object> map = DataMap.get(sstInf.getInfRealEnv());
                for (Map.Entry entry : map.entrySet()) {
                    build.addHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
            if (SysUtils.isNotVoid(sstInf.getAuthName()) && SysUtils.isNotVoid(sstInf.getAuthValue())) {
                build.addHeader(sstInf.getAuthName(), sstInf.getAuthValue());
            }
            //
            Request request = build.build();
            start = System.currentTimeMillis();
            sstInf.setRequestTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(SysUtils.isVoid(sstInf.getTimeOut()) ? TimeOutContant.TIME_OUT : Long.valueOf(sstInf.getTimeOut()), TimeUnit.MILLISECONDS);
            execute = call.execute();
            end = System.currentTimeMillis();
            sstInf.setResponseTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            resultView.setStatus(String.valueOf(execute.code()));
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                if (sstInf.isRecordVersion()) {
                    InfItemResult infItemResult = new InfItemResult(resultView.getStatus(), sstInf.getInfId(), execute.body().string());
                    resultView.setResult(infItemResult);
                }
            }
        } catch (InterruptedIOException e) {
            //处理请求超时
            end = System.currentTimeMillis();
            resultView.setStatus("1");
            resultView.setErrorType(1);
            log.error("okhttp POST请求超时--{0}", e);
        } catch (IOException e) {
            end = System.currentTimeMillis();
            resultView.setStatus("1");
            log.error("okhttp POST请求失败--{0}", e);
        }
        resultView.setConsumeTime(end - start);
        resultView.setInfName(sstInf.getInfName());
        resultView.setInfId(sstInf.getInfId());
        resultView.setPath(sstInf.getInfUrl());
        resultView.setMethodType(sstInf.getInfMethod());
        return resultView;
    }

    public static ResultView requestGetByAT(SstInf sstInf) {
        Response execute;
        ResultView resultView = new ResultView();
        long start = System.currentTimeMillis();
        long end;
        try {
            //Header
            String infRequest = SysUtils.isNotVoid(sstInf.getInfRequest()) ? sstInf.getInfRequest() : null;
            String method = SysUtils.isNotVoid(sstInf.getInfMethod()) ? sstInf.getInfMethod() : "GET";
            //拼装GET参数和URL
            String url = sstInf.getInfFullUrl();
            StringBuffer sb = new StringBuffer();
            sb.append(url);
            sb.append("?");
            if (SysUtils.isNotVoid(infRequest)) {
                try {
                    if(infRequest.length()>4){
                        HashMap map = JSONUtil.toBean(infRequest, HashMap.class);
                        StringJoiner param = new StringJoiner("&");
                        map.forEach((key, value) -> param.add(key + "=" + value));
                        sb.append(param);
                    }
                } catch (Exception e) {
                    log.error("組裝参数失败：{}", e.getMessage());
                }
            }
            Request.Builder build = new Request.Builder()
                    .url(sb.toString())
                    .method(method, null)
                    .addHeader("Content-Type", SysUtils.isNotVoid(sstInf.getContentType()) ? sstInf.getContentType() : "application/json");
            if (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv()))) {
                Map<String, Object> map = DataMap.get(sstInf.getInfRealEnv());
                for (Map.Entry entry : map.entrySet()) {
                    build.addHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
            if (SysUtils.isNotVoid(sstInf.getAuthName()) && SysUtils.isNotVoid(sstInf.getAuthValue())) {
                build.addHeader(sstInf.getAuthName(), sstInf.getAuthValue());
            }
            //
            Request request = build.build();
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(sstInf.getTimeOut() == null ? TimeOutContant.TIME_OUT : Long.valueOf(sstInf.getTimeOut()), TimeUnit.MILLISECONDS);
            execute = call.execute();

            end = System.currentTimeMillis();
            sstInf.setResponseTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            resultView.setStatus(String.valueOf(execute.code()));
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                if (sstInf.isRecordVersion()) {
                    InfItemResult infItemResult = new InfItemResult(resultView.getStatus(), sstInf.getInfId(), execute.body().string());
                    resultView.setResult(infItemResult);
                }
            }
        } catch (InterruptedIOException e) {
            //处理请求超时
            end = System.currentTimeMillis();
            resultView.setStatus("1");
            resultView.setErrorType(1);
            log.error("okhttp POST请求超时--{0}", e);
        } catch (IOException e) {
            end = System.currentTimeMillis();
            resultView.setStatus("1");
            log.error("okhttp 请求失败--{0}", e);
        }
        resultView.setConsumeTime(end - start);
        resultView.setInfName(sstInf.getInfName());
        resultView.setInfId(sstInf.getInfId());
        resultView.setPath(sstInf.getInfUrl());
        resultView.setMethodType(sstInf.getInfMethod());
        return resultView;
    }

}
